{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import struct\n",
    "\n",
    "\n",
    "class MnistData:\n",
    "    def __init__(self, train_image_path, train_label_path,\n",
    "                 test_image_path, test_label_path):\n",
    "        # 训练集和测试集的文件路径\n",
    "        self.train_image_path = train_image_path\n",
    "        self.train_label_path = train_label_path\n",
    "        self.test_image_path = test_image_path\n",
    "        self.test_label_path = test_label_path\n",
    "\n",
    "        # 获取训练集和测试集数据\n",
    "        # get_data()方法，参数为0获取训练集数据，参数为1获取测试集\n",
    "        self.train_images, self.train_labels = self.get_data(0)\n",
    "        self.test_images, self.test_labels = self.get_data(1)\n",
    "\n",
    "    def get_data(self, data_type):\n",
    "        if data_type == 0:  # 获取训练集数据\n",
    "            image_path = self.train_image_path\n",
    "            label_path = self.train_label_path\n",
    "        else:  # 获取测试集数据\n",
    "            image_path = self.test_image_path\n",
    "            label_path = self.test_label_path\n",
    "\n",
    "        with open(image_path, 'rb') as file1:\n",
    "            image_file = file1.read()\n",
    "        with open(label_path, 'rb') as file2:\n",
    "            label_file = file2.read()\n",
    "\n",
    "        label_index = 0\n",
    "        image_index = 0\n",
    "        labels = []\n",
    "        images = []\n",
    "\n",
    "        # 读取训练集图像数据文件的文件信息\n",
    "        magic, num_of_datasets, rows, columns = struct.unpack_from('>IIII',\n",
    "                                                                   image_file, image_index)\n",
    "        image_index += struct.calcsize('>IIII')\n",
    "\n",
    "        for i in range(num_of_datasets):\n",
    "            # 读取784个unsigned byte，即一副图像的所有像素值\n",
    "            temp = struct.unpack_from('>784B', image_file, image_index)\n",
    "            # 将读取的像素数据转换成28*28的矩阵\n",
    "            temp = np.reshape(temp, (28, 28))\n",
    "            # 归一化处理\n",
    "            temp = temp / 255\n",
    "            images.append(temp)\n",
    "            image_index += struct.calcsize('>784B')  # 每次增加784B\n",
    "\n",
    "        # 跳过描述信息\n",
    "        label_index += struct.calcsize('>II')\n",
    "        labels = struct.unpack_from('>' + str(num_of_datasets) + 'B', label_file, label_index)\n",
    "\n",
    "        images = np.array(images)\n",
    "        images = images.reshape(num_of_datasets, 28, 28 )\n",
    "        # one-hot\n",
    "        labels = np.eye(10)[np.array(labels)]\n",
    "\n",
    "        return images, labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'>\n",
      "<class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "source": [
    "train_image_path = './data/train-images-idx3-ubyte'\n",
    "train_label_path = './data/train-labels-idx1-ubyte'\n",
    "test_image_path = './data/t10k-images-idx3-ubyte'\n",
    "test_label_path = './data/t10k-labels-idx1-ubyte'\n",
    "\n",
    "data = MnistData(train_image_path, train_label_path,\n",
    "                 test_image_path, test_label_path)\n",
    "\n",
    "print(type(data.train_images))\n",
    "print(type(data.train_labels))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(type(data.train_images))\n",
    "print(type(data.train_labels))\n",
    "\n",
    "print(type(data.train_images[0]))\n",
    "print(type(data.train_labels[0]))\n",
    "\n",
    "print(data.train_images[0])\n",
    "print(data.train_labels[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "W0612 05:44:11.203917 139730924926720 tf_logging.py:161] <tensorflow.python.keras.layers.recurrent.UnifiedLSTM object at 0x7f14fc1af940>: Note that this layer is not optimized for performance. Please use tf.keras.layers.CuDNNLSTM for better performance on GPU.\n",
      "W0612 05:44:11.207954 139730924926720 tf_logging.py:161] <tensorflow.python.keras.layers.recurrent.UnifiedLSTM object at 0x7f14742a6668>: Note that this layer is not optimized for performance. Please use tf.keras.layers.CuDNNLSTM for better performance on GPU.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/5\n",
      "60000/60000 [==============================] - 11s 190us/sample - loss: 0.4478 - accuracy: 0.8595\n",
      "Epoch 2/5\n",
      "60000/60000 [==============================] - 11s 191us/sample - loss: 0.1256 - accuracy: 0.9628\n",
      "Epoch 3/5\n",
      "60000/60000 [==============================] - 11s 191us/sample - loss: 0.0868 - accuracy: 0.9743\n",
      "Epoch 4/5\n",
      "60000/60000 [==============================] - 11s 187us/sample - loss: 0.0629 - accuracy: 0.9810\n",
      "Epoch 5/5\n",
      "60000/60000 [==============================] - 11s 184us/sample - loss: 0.0525 - accuracy: 0.9848\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<tensorflow.python.keras.callbacks.History at 0x7f14742a9128>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "model = tf.keras.models.Sequential([\n",
    "    tf.keras.layers.LSTM(64, return_sequences=True, input_shape=(28, 28)),\n",
    "    tf.keras.layers.LSTM(32),\n",
    "    tf.keras.layers.Dense(10, activation='softmax')\n",
    "])\n",
    "\n",
    "model.compile(loss='categorical_crossentropy',\n",
    "              optimizer='rmsprop',\n",
    "              metrics=['accuracy'])\n",
    "\n",
    "model.fit(data.train_images, data.train_labels, epochs=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/5\n",
      "60000/60000 [==============================] - 6s 98us/sample - loss: 0.2196 - accuracy: 0.9340\n",
      "Epoch 2/5\n",
      "60000/60000 [==============================] - 6s 95us/sample - loss: 0.0952 - accuracy: 0.9709\n",
      "Epoch 3/5\n",
      "60000/60000 [==============================] - 6s 93us/sample - loss: 0.0681 - accuracy: 0.9788\n",
      "Epoch 4/5\n",
      "60000/60000 [==============================] - 6s 94us/sample - loss: 0.0534 - accuracy: 0.9826\n",
      "Epoch 5/5\n",
      "60000/60000 [==============================] - 6s 96us/sample - loss: 0.0432 - accuracy: 0.9854\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<tensorflow.python.keras.callbacks.History at 0x7fde29c1bf98>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "model = tf.keras.models.Sequential([\n",
    "  tf.keras.layers.Flatten(input_shape=(28, 28)),\n",
    "  tf.keras.layers.Dense(512, activation=tf.nn.relu),\n",
    "  tf.keras.layers.Dropout(0.2),\n",
    "  tf.keras.layers.Dense(10, activation=tf.nn.softmax)\n",
    "])\n",
    "model.compile(optimizer='adam',\n",
    "              loss='categorical_crossentropy',\n",
    "              metrics=['accuracy'])\n",
    "\n",
    "model.fit(data.train_images, data.train_labels, epochs=5)\n",
    "# model.evaluate(x_test, y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10000/10000 [==============================] - 1s 69us/sample - loss: 0.0719 - accuracy: 0.9790\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[0.07191091472541447, 0.979]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.evaluate(data.test_images, data.test_labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'numpy.ndarray'>\n",
      "<class 'numpy.ndarray'>\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "mnist = tf.keras.datasets.mnist\n",
    "\n",
    "(x_train, y_train),(x_test, y_test) = mnist.load_data()\n",
    "x_train, x_test = x_train / 255.0, x_test / 255.0\n",
    "\n",
    "print(type(x_train))\n",
    "print(type(x_test))\n",
    "\n",
    "# print(x_train[0])\n",
    "print(y_train[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
